clojure.core のマップに関する var
Clojure におけるマップは、clojure.lang.IPersistentMap インタフェースを実装したインスタンス
マップ(連想配列): clojure.lang.PersistentArrayMap
ハッシュマップ: clojure.lang.PersistentHashMap
ソート済みマップ: clojure.lang.PersistentTreeMap
関数
hash-map: キーと値のペアを渡すと、新しいハッシュマップを生成して返す
code:clj
(hash-map :a 1 :b 2 :c 3) ; {:c 3, :b 2, :a 1}
引数を渡さない場合、空のハッシュマップを返す
code:clj
(hash-map) ; {}
キーが重複した場合、最後に指定された値が使用される
code:clj
(hash-map :a 1 :b 2 :a 3) ; {:b 2, :a 3}
sorted-map: キーと値のペアを渡すと、ソート済みのマップを生成して返す
キーの順序は昇順になる
code:clj
(sorted-map :a 1 :c 3 :b 2) ; {:a 1, :b 2, :c 3}
(sorted-map :a 1 :a 2) ; {:a 2}
sorted-map-by: 引数の比較関数を用いて、ソート済みのマップを生成して返す
code:clj
(sorted-map-by > 3 "three" 1 "one" 2 "two") ; {3 "three", 2 "two", 1 "one"}
キーが重複した場合、最後に指定さあれた値が使用される
code:clj
(sorted-map-by #(compare (count %2) (count %1)) "three" 3
"one" 1
"two" 2)
;; {"three" 3, "one" 2}
map?: 引数が IPersistentMap インタフェースを実装しているか
code:clj
(map map? [ #{} {}]) ; (false false false true) assoc: マップやベクタに要素を追加・更新する
マップの場合、指定されたキーの値を新しい値に置き換えた、新しいマップを返す
code:clj
(assoc {} :a 1) ; {:a 1}
(assoc {:a 1 :b 2 } :a 3 :c 4) ; {:a 3, :b 2, :c 4}
ベクタの場合、指定されたインデックスに新しい値を格納した、新しいベクタを返す
code:clj
範囲外のインデックスが指定された場合、例外(IndexOutOfBoundsException)を吐く
code:clj
assoc-in: assoc のネスト対応版
ネストしたマップから、指定されたキーパスに沿う値を更新する
code:clj
(assoc-in {:a {:b 2}} :a :b 3) ; {:a {:b 3}} キーが存在しない場合は生成される
code:clj
(assoc-in {} :a :b 1) ; {:a {:b 1}} (assoc-in {:a {:b 2} :c 4} :a :d 3) ; :a {:b 2, :d 3}, :c 4} (assoc-in {} :a :b :c 1) ; {:a {:b {:c 1}}} dissoc: 指定されたキーと値を削除した、新しいマップを返す
code:clj
(dissoc {:a 1 :b 2 :c 3} :b) ; {:a 1, :c 3}
(dissoc {:a 1 :b 2 :c 3} :c) ; {:a 1, :b 2}
キーが存在しない場合は、何も行わない
code:clj
(dissoc {} :a :b :c) ; {}
get-in: ネストしたマップから、指定されたキーパス(シーケンス)に沿って値を取得する code:clj
(get-in {:a {:b 1 :c 2}} :a :b) ; 1 キーが見つからない場合は nil を返すが、第 3 引数でデフォルト値を渡すことも可能
code:clj
(get-in {:a {:b 1 :c 2}} :a :d) ; nil (get-in {:a {:b 1 :c 2}} :a :d "not-found") ; "not-found" select-keys: マップとキーのシーケンスを受け取り、そのキーと値のみを持つ新しいマップを生成して返す
code:clj
(def data {:a 1 :b 2 :c 3})
(select-keys data :a :c) ; {:a 1, :c 3} 存在しないキーは無視される
code:clj
空のシーケンスが渡された場合、空マップを返す
code:clj
(select-keys data []) ; {}
update: マップとキー、関数を受け取り、キーの値を関数に適用した結果を値とする、新しいマップを返す
code:clj
(update {:a 1 :b 2} :b inc) ; {:a 1, :b 3}
(update {:a 1 :b 2} :a + 10) ; {:a 11, :b 2}
要素が存在しない場合は、関数に nil が渡される
code:clj
update {:a 1 :b 2} :c (constantly 42)) ; {:a 1, :b 2, :c 42}
update-in: update のネスト対応版
ネストしたマップから、指定されたキーパスに沿う値に関数を適用し、その結果を値とする新しいマップを返す
code:clj
(def m {:a {:b 1 :c 2} :x 5})
(update-in m :a assoc :b 3 :d 4) ;; {:a {:b 3, :c 2, :d 4}, :x 5}
assoc-in 同様、キーが存在しない場合は生成される
code:clj
(update-in m :y :z (fn x (if x (inc x) 1))) ;; {:a {:b 1, :c 2}, :x 5, :y {:z 1}}
update-vals: マップと関数を受け取り、各キー値を関数に適用した結果を値とする、新しいマップを返す
code:clj
(update-vals {:a 1 :b 2 :c 3} inc) ; {:a 2, :b 3, :c 4}
(update-vals {:a 1 :b 2 :c 3} #(* % %)) ; {:a 1, :b 4, :c 9} (update-vals {:a 1 :b 2 :c 3} (fn x (if (odd? x) (inc x) (dec x)))) ;; {:a 2, :b 1, :c 4}
update-keys: update-vals のキー版
マップと関数を受け取り、各キーを関数に適用して得られた結果を新しいキーとする、新しいマップを返す
code:clj
(update-keys {:one 1 :two 2 :three 3} name)
;; {"one" 1, "two" 2, "three" 3}
merge: 複数のマップを 1 つにマージする
code:clj
(merge {:a 1} {:b 2} {:c 3}) ; {:a 1, :b 2, :c 3}
同じキーが複数マップに存在する場合、一番最後にマージされたキーが選択される(後勝ち) code:clj
(merge {:a 1 :b 2} {:b 3 :c 4}) ; {:a 1, :b 3, :c 4}
引数を渡さない場合、nil を返す
code:clj
(merge) ; nil
merge-with: 複数のマップを 1 つにマージする
同じキーが複数マップに存在する場合、指定された関数を用いてそれらの値を結合する
code:clj
(merge-with + {:a 1 :b 2} {:a 3 :c 4})
;; {:a 4, :b 2, :c 4}
(merge-with str {:a "A"} {:a "a" :b "B"})
;; {:a "Aa", :b "B"}
(merge-with (fn x y (str x "-" y)) {:a 1 :b 2} {:a 3 :c 4}) ;; {:a "1-3", :b 2, :c 4}
find: マップからキーに対応するマップエントリ(キーと値のペア: clojure.lang.MapEntry)を取得する
code:clj
(find {:a 1 :b 2 :c 3} :a) ; :a 1 存在しない場合は nil を返す
code:clj
(find {:a 1 :b 2 :c 3} :d) ; nil
map-entry?: 引数がマップエントリか
code:clj
(type (first {:a 1 :b 2})) ; clojure.lang.MapEntry
(map-entry? (first {:a 1 :b 2})) ; true
key: マップエントリのキーを返す
code:clj
(map key {:a 1 :b 2 :c 3}) ; (:a :b :c)
val: マップエントリの値を返す
code:clj
(map val {:a 1 :b 2 :c 3}) ; (1 2 3)
struct / struct-map : 構造体のインスタンス(clojure.lang.PersistentStructMap)を生成する
struct は値を定義順にセットする必要があるが、struct-map ではキーを指定して値をセットできる
code:clj
(defstruct person :name :age)
(struct person "Bob" 20) ; {:name "Bob", :age 20}
(struct-map person :age 20 :name "Bob") ; {:name "Bob", :age 20}
create-struct: 構造体の定義(clojure.lang.PersistentStructMap$Def)を生成する
defstruct とは異なり、var への 束縛 はしない code:clj
(type (create-struct :1 :2))
array-map: マップを作成する
code:clj
(array-map :a 1 :b 2 :c 3) ; {:a 1, :b 2, :c 3}
{...} と同じ
code:clj
(type (array-map :a 1 :b 2 :c 3))
clojure.lang.PersistentArrayMap
(type {:a 1 :b 2 :c 3})
clojure.lang.PersistentArrayMap
マクロ
defsturct: 構造体 の定義を生成し、 var に束縛する code:clj